#include <iostream>
#include <string>
#include <sstream>
#include <iomanip>
#include <type_traits>

//===========================================
// 特征(Traits)部分 - 为不同类型提供格式化信息
//===========================================

// 基本特征模板
template <typename T>
struct FormatTraits {
    static std::string toString(const T& value) {
        std::ostringstream oss;
        oss << value;
        return oss.str();
    }
    
    static constexpr const char* typeName() {
        return "Unknown";
    }
};

// 整数类型的特化
template <>
struct FormatTraits<int> {
    static std::string toString(const int& value) {
        return std::to_string(value);
    }
    
    static constexpr const char* typeName() {
        return "Integer";
    }
};

// 浮点类型的特化
template <>
struct FormatTraits<double> {
    static std::string toString(const double& value) {
        std::ostringstream oss;
        oss << std::fixed << std::setprecision(2) << value;
        return oss.str();
    }
    
    static constexpr const char* typeName() {
        return "Double";
    }
};

// 字符串类型的特化
template <>
struct FormatTraits<std::string> {
    static std::string toString(const std::string& value) {
        return value;
    }
    
    static constexpr const char* typeName() {
        return "String";
    }
};

//===========================================
// SFINAE辅助工具 - 检测策略是否有format方法
//===========================================

// 使用void_t技术检测是否存在format方法
template <typename, typename = void>
struct HasFormatMethod : std::false_type {};

// ========================================
// 解析
// 1. T::template format<int> - 访问T的一个名为format的模板成员函数，并以int作为模板参数
// 2. std::declval<int>() - 创建一个int类型的假想值（不需要实际构造）
// 3. std::declval<FormatTraits<int>>() - 创建一个FormatTraits<int>类型的假想值
// 
// 我们使用了 T::template format 而不是 std::declval<T>().template format 的原因是我们假设 format 是一个静态成员函数模板。
// 静态成员函数 通过类名直接调用: ClassName::functionName()
// ========================================

template <typename T>
struct HasFormatMethod<
    T, 
    std::void_t<decltype(
        T::template format<int>(std::declval<int>(), std::declval<FormatTraits<int>>())
    )>
> : std::true_type {};

//===========================================
// 策略(Policy)部分 - 定义不同的格式化策略
//===========================================

// 普通输出策略 - 作为默认策略
class PlainPolicy {
public:
    template <typename T>
    static std::string format(const T& value, const FormatTraits<T>& traits) {
        return traits.toString(value);
    }
};

// 带类型信息的输出策略
class TypedPolicy {
public:
    template <typename T>
    static std::string format(const T& value, const FormatTraits<T>& traits) {
        return std::string(traits.typeName()) + ": " + traits.toString(value);
    }
};

// 带装饰的输出策略
class DecoratedPolicy {
public:
    template <typename T>
    static std::string format(const T& value, const FormatTraits<T>& traits) {
        return "[ " + traits.toString(value) + " ]";
    }
};

// 一个缺少format方法的策略（用于演示SFINAE）
class InvalidPolicy {
public:
    // 没有定义format方法
    template <typename T>
    static std::string wrongMethodName(const T& value, const FormatTraits<T>& traits) {
        return "This won't be called";
    }
};

//===========================================
// 主格式化器类 - 使用SFINAE优化
//===========================================

// 前向声明
template <
    typename T,
    typename Policy = PlainPolicy,
    typename Traits = FormatTraits<T>,
    bool HasFormat = HasFormatMethod<Policy>::value
>
class Formatter;

// 有效策略的特化版本
template <
    typename T,
    typename Policy,
    typename Traits
>
class Formatter<T, Policy, Traits, true> {
public:
    static std::string format(const T& value) {
        return Policy::template format<T>(value, Traits());
    }
    
    template <typename NewPolicy, 
              typename = std::enable_if_t<HasFormatMethod<NewPolicy>::value>>
    static std::string formatWith(const T& value) {
        return NewPolicy::template format<T>(value, Traits());
    }
};

// 无效策略的特化版本
template <
    typename T,
    typename Policy,
    typename Traits
>
class Formatter<T, Policy, Traits, false> {
public:
    // 提供友好的编译时错误信息
    static_assert(HasFormatMethod<Policy>::value, 
                 "Policy must provide a 'format<T>(const T&, const FormatTraits<T>&)' method");
    
    static std::string format(const T& value) {
        // 这个函数不会被实际调用，因为static_assert会阻止编译
        return "";
    }
    
    // 提供一个退回到默认策略的版本
    static std::string formatFallback(const T& value) {
        std::cerr << "Warning: Using fallback policy because provided policy is invalid" << std::endl;
        return PlainPolicy::template format<T>(value, Traits());
    }
};

//===========================================
// 示例用法
//===========================================

int main() {
    int intValue = 42;
    double doubleValue = 3.14159;
    std::string stringValue = "Hello, World!";
    
    // 使用默认策略(PlainPolicy)
    std::cout << "默认格式化: \n";
    std::cout << "Int: " << Formatter<int>::format(intValue) << std::endl;
    std::cout << "Double: " << Formatter<double>::format(doubleValue) << std::endl;
    std::cout << "String: " << Formatter<std::string>::format(stringValue) << std::endl;
    
    std::cout << "\n带类型信息的格式化: \n";
    std::cout << "Int: " << Formatter<int, TypedPolicy>::format(intValue) << std::endl;
    std::cout << "Double: " << Formatter<double, TypedPolicy>::format(doubleValue) << std::endl;
    std::cout << "String: " << Formatter<std::string, TypedPolicy>::format(stringValue) << std::endl;
    
    std::cout << "\n装饰格式化: \n";
    std::cout << "Int: " << Formatter<int, DecoratedPolicy>::format(intValue) << std::endl;
    std::cout << "Double: " << Formatter<double, DecoratedPolicy>::format(doubleValue) << std::endl;
    std::cout << "String: " << Formatter<std::string, DecoratedPolicy>::format(stringValue) << std::endl;
    
    // 使用链式接口在运行时选择策略
    std::cout << "\n运行时选择策略: \n";
    std::cout << "Int with TypedPolicy: " 
              << Formatter<int>::formatWith<TypedPolicy>(intValue) << std::endl;
    std::cout << "Double with DecoratedPolicy: " 
              << Formatter<double>::formatWith<DecoratedPolicy>(doubleValue) << std::endl;
    
    // 使用无效策略的情况 - 这行会导致编译错误，但错误信息更友好
    // std::cout << Formatter<int, InvalidPolicy>::format(intValue) << std::endl;
    
    // 但这行会使用fallback方法，不会导致编译错误
    // std::cout << "Fallback: " << Formatter<int, InvalidPolicy>::formatFallback(intValue) << std::endl;
    
    return 0;
}